package org.dragonnova.business.service.impl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;

import org.dragonnova.business.dao.TagDao;
import org.dragonnova.business.dao.TagValueDao;
import org.dragonnova.business.dao.ThresholdDao;
import org.dragonnova.business.dto.DeviceTagDto;
import org.dragonnova.business.dto.PageDto;
import org.dragonnova.business.dto.TagValueDto;
import org.dragonnova.business.model.DeviceBox;
import org.dragonnova.business.model.DeviceTag;
import org.dragonnova.business.model.Report;
import org.dragonnova.business.model.TagReports;
import org.dragonnova.business.model.TagValue;
import org.dragonnova.business.model.Threshold;
import org.dragonnova.business.service.TagService;
import org.dragonnova.business.util.IOTBeanUtils;
import org.junit.Test;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.base.pub.util.CoordinateUtil;
import com.base.pub.util.DateUtils;
import com.base.pub.util.LatLng;
import com.mysql.jdbc.StringUtils;

import net.sf.cglib.beans.BeanCopier;

@Service("tagService")
public class TagServiceImpl extends BaseServiceImpl implements TagService {
	@Autowired(required = true)
	private TagDao tagDao;
	@Autowired(required = true)
	private TagValueDao tagValueDao;
	@Autowired(required = true)
	private ThresholdDao thresholdDao;
	private String timeType = "yyyy-MM-dd HH:dd:mm";

	@Override
	public boolean addDeviceTag(DeviceTag deviceTag) throws Exception {
		int result = tagDao.addDeviceTag(deviceTag);
		if (result > 0) {
			Threshold ts = new Threshold();
			ts.setTagSn(deviceTag.getSn());
			ts.setHumAlert(deviceTag.getHumAlert1());
			ts.setTempAlert(deviceTag.getTempAlert1());
			result = thresholdDao.saveOrUpdateThreshold(ts);
			return result > 0 ? true : false;
		}
		return false;
	}

	@Override
	public boolean updateDeviceTag(DeviceTag deviceTag) throws Exception {
		int result = tagDao.updateDeviceTag(deviceTag);
		if (result > 0) {
			Threshold ts = new Threshold();
			ts.setTagSn(deviceTag.getSn());
			ts.setHumAlert(deviceTag.getHumAlert1());
			ts.setTempAlert(deviceTag.getTempAlert1());
			ts.setUpdatetime(DateUtils.getTimes(new Date(), timeType));
			result = thresholdDao.saveOrUpdateThreshold(ts);
			return result > 0 ? true : false;
		}
		return false;
	}

	@Override
	public List<DeviceTag> findDeviceTag(Integer userId, String searchText, String id, Integer orderType)
			throws Exception {
		StringBuffer order = getOrderStr(orderType);
		if (searchText != null)
			searchText = "%" + searchText + "%";
		List<DeviceTag> list = tagDao.findDeviceTag(userId, searchText, id, order.toString());
		long t1 = System.currentTimeMillis();
		for (DeviceTag tag : list) {
			TagValue values = tagValueDao.findNewestValue(tag.getSn());
			tag.setTagValue(values);
			setTagStatus(tag);
		}
		long t2 = System.currentTimeMillis();
		// System.err.println("\n耗时："+(t2-t1)+"\n");
		return doOrderByTime(orderType, list);

	}

	private StringBuffer getOrderStr(Integer orderType) {
		StringBuffer order = new StringBuffer(" order by ");
		if (orderType == null) {
			order.append(" a.id desc");
		} else if (orderType == 3) {
			order.append(" a.zone  ");
		} else if (orderType == 4) {
			order.append(" a.zone desc ");
		} else {
			order.append(" a.id desc ");
		}
		return order;
	}

	/**
	 * 时间排序
	 * 
	 * @param orderType
	 * @param list
	 * @return
	 * @throws Exception
	 */
	private List<DeviceTag> doOrderByTime(Integer orderType, List<DeviceTag> list) throws Exception {
		if (orderType == null || orderType == 1) {
			Collections.sort(list, new Comparator<DeviceTag>() {
				@Override
				public int compare(DeviceTag a, DeviceTag b) {
					TagValue v1 = a.getTagValue();
					TagValue v2 = b.getTagValue();
					if (v1 != null && v2 != null) {
						return (DateUtils.getDigit(v2.getUpdatetime()) - DateUtils.getDigit(v1.getUpdatetime())) > 0 ? 1
								: -1;
					}
					return 0;
				}

			});

		} else if (orderType == 2) {
			Collections.sort(list, new Comparator<DeviceTag>() {
				@Override
				public int compare(DeviceTag a, DeviceTag b) {
					TagValue v1 = a.getTagValue();
					TagValue v2 = b.getTagValue();
					if (v1 != null && v2 != null) {
						return (DateUtils.getDigit(v2.getUpdatetime()) - DateUtils.getDigit(v1.getUpdatetime())) > 0
								? -1 : 1;
					}
					return 0;
				}

			});
		}
		return list;
	}

	private void setTagStatus(DeviceTag tag) {
		TagValue tagValue = tag.getTagValue();
		if (tagValue == null) {
			return;
		}
		int status = 0;
		String[] tempAlert = tag.getTempAlert();
		String[] humAlert = tag.getHumAlert();
		if (tempAlert != null && tagValue.getTemp() != null) {
			Float tempMin = Float.parseFloat(tempAlert[0]);
			Float tempMax = Float.parseFloat(tempAlert[1]);
			if (tagValue.getTemp() > tempMax || tagValue.getTemp() < tempMin) {
				status = 1;
			}
		}
		if (humAlert != null && tagValue.getHum() != null) {
			Float hunMin = Float.parseFloat(humAlert[0]);
			Float humMax = Float.parseFloat(humAlert[1]);
			if (tagValue.getHum() > humMax || tagValue.getHum() < hunMin) {
				status = status > 0 ? 3 : 2;
			}
		}
		tagValue.setStatus(status);
	}

	@Override
	public List<DeviceBox> findDeviceBox(int userId, String searchText, String id) throws Exception {
		List<DeviceBox> list = tagDao.findDeviceBox(userId, searchText, id);
		for (DeviceBox box : list) {
			TagValue tagValue = findNewestValue(box.getSn());
			if (tagValue != null && tagValue.getLatitude() != null) {
				LatLng latLng = CoordinateUtil.wgsToGcj(tagValue.getLatitude(), tagValue.getLongitude());
				tagValue.setLatitude(latLng.latitude);
				tagValue.setLongitude(latLng.longitude);
			}
			box.setTagValue(tagValue);
		}
		return list;
	}

	@Override
	public boolean delTagById(String sn) throws Exception {
		int result = tagDao.delTagById(sn);
		return result > 0 ? true : false;
	}

	/**
	 * 1. 一天， 一天的按2min一个数据显示； 2. 3天的按5min显示； 3. 7天按15min显示； 4. 30天按1h； 5.
	 * 自主选择时间，按30天划分，以上按天来统计，最高90天；以下按照1-4条来做；
	 */
	public TagReports getReport(Integer userId, String tagId, String startTime, String endTime, Integer days,
			Integer type) throws Exception {
		long t1 = System.currentTimeMillis();
		int unit = 2 * 60;// 时间单位
		long startSec = 0, endSec;// 一小时
		String timeType = "yyyy-MM-dd", unitStr = "";
		endSec = DateUtils.getTimeSec(endTime, timeType) / 1000 + 86400l;
		if (type == 2) {
			startSec = DateUtils.getTimeSec(startTime, timeType) / 1000;
			days = (int) ((endSec - startSec) / 86400l);
		} else {
			startSec = endSec - days * 86400l;
		}
		if (days == 1) {
			unitStr = "2min";
			unit = 2 * 60;
		} else if (days <= 3) {
			unitStr = "5min";
			unit = 5 * 60;
		} else if (days <= 7) {
			unitStr = "15min";
			unit = 15 * 60;
		} else if (days <= 30) {
			unitStr = "1hour";
			unit = 60 * 60;
		} else {
			unitStr = "1day";
			unit = 24 * 60 * 60;
		}
		List<DeviceTag> dtList = tagDao.findDeviceTag(userId, null, tagId, null);
		TagReports tr = new TagReports();
		String sn = "";
		if (dtList.size() > 0) {
			sn = dtList.get(0).getSn();
			tr.setTagId(tagId);
			tr.setSn(dtList.get(0).getSn());
			tr.setDays(days + "");
			tr.setUnit(unitStr);
			tr.setTitle(dtList.get(0).getTitle());
			tr.setStartTime(DateUtils.getTimes(new Date(startSec * 1000l), timeType));
			tr.setEndTime(endTime);
		}
		List<Report> reports = tagValueDao.findTagValueAvg(sn, unit, startSec, endSec);
		tr.setReports(reports);
		System.err.println("耗时：" + (System.currentTimeMillis() - t1));
		return tr;
	}

	@Override
	public void addTestData(List<TagValue> list) {
		try {
			tagValueDao.addTestData(list);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@Override
	public boolean addTagValue(TagValue tagValue) throws Exception {
		int result = tagValueDao.addTagValue(tagValue);
		return result > 0 ? true : false;
	}

	@Override
	public boolean delValueAndThresoldByTagSn(String tagSn) throws Exception {
		thresholdDao.delThreshold(tagSn);
		int result = tagValueDao.delTagValueByTagSn(tagSn);
		return result > 0 ? true : false;
	}

	@Override
	public TagValue findNewestValue(String tagSn) throws Exception {
		return tagValueDao.findNewestValue(tagSn);
	}

	@Override
	public boolean updateBox(DeviceBox box) throws Exception {
		int result = tagDao.updateBox(box);
		return result > 0 ? true : false;
	}

	@Override
	public boolean isUsedZoneId(Integer zoneId) throws Exception {
		int count = tagDao.findCountByZoneId(zoneId);
		System.out.println("count=" + count);
		return count > 0;
	}

	@Override
	public DeviceTag findDeviceTagBySn(String sn) throws Exception {
		return tagDao.findDeviceTagBySn(sn);
	}

	@Override
	public PageDto<List<DeviceTag>> findTagByPage(Integer userId, Integer indexPage, Integer pageSize, Integer orderType,
			String searchText) throws Exception {
		if (!StringUtils.isNullOrEmpty(searchText))
			searchText = "%" + searchText + "%";
		Long totalCount = tagDao.getTotalCount(userId, searchText);
		PageDto<List<DeviceTag>> page = new PageDto<List<DeviceTag>>();
		page.setList(new ArrayList<>());
		if (pageSize != null && pageSize>0) {
			page.setPageSize(pageSize);
		}
		int start = (indexPage - 1) * page.getPageSize();
		StringBuffer order = getOrderStr(orderType);
		List<DeviceTag> list = tagDao.findTagByPage(userId, start, page.getPageSize(), searchText, order.toString());
		for (DeviceTag tag : list) {
			TagValue values = tagValueDao.findNewestValue(tag.getSn());
			tag.setTagValue(values);
			setTagStatus(tag);
		}
		page.setList(list);
		page.setTotalCount(totalCount);
		page.setIndexPage(indexPage);
		return page;
	}

}
